/*
 *
 *      Copyright (c) 2018-2025, madp All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: 成都文思海辉金信软件有限公司
 *
 */

package com.pactera.madp.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pactera.madp.admin.api.constant.SyncConstant;
import com.pactera.madp.admin.api.constant.UpmsConstant;
import com.pactera.madp.admin.api.dto.DeptTree;
import com.pactera.madp.admin.api.dto.SyncSysDept;
import com.pactera.madp.admin.api.dto.TreeNode;
import com.pactera.madp.admin.api.entity.*;
import com.pactera.madp.admin.api.feign.RemoteSyncCpService;
import com.pactera.madp.admin.api.feign.RemoteWxService;
import com.pactera.madp.admin.api.vo.DeptLineDeptVO;
import com.pactera.madp.admin.api.vo.TreeUtil;
import com.pactera.madp.admin.mapper.*;
import com.pactera.madp.admin.service.*;
import com.pactera.madp.common.core.constant.SecurityConstants;
import com.pactera.madp.common.core.util.R;
import com.pactera.madp.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门管理 服务实现类
 * </p>
 *
 * @author madp
 * @since 2018-01-20
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {
	private final SysDeptRelationService sysDeptRelationService;
	private final SysWxDeptRelationService sysWxDeptRelationService;
	private final RemoteWxService remoteWxService;
	RemoteSyncCpService remoteSyncCpService;
	private final SysDeptRelationMapper sysDeptRelationMapper;
	private final SysDeptLineDeptMapper sysDeptLineDeptMapper;
	private final SysDeptLineDeptService sysDeptLineDeptService;
	private final SysDeptUserService sysDeptUserService;
	private final SysUserMapper sysUserMapper;

	/**
	 * 添加信息部门
	 *
	 * @param dept 部门
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveDept(SysDept dept) {
		//系统部门创建
		SysDept sysDept = new SysDept();
		BeanUtils.copyProperties(dept, sysDept);
		this.save(sysDept);
		sysDeptRelationService.insertDeptRelation(sysDept);
		dept.setDeptId(sysDept.getDeptId());

		return Boolean.TRUE;
	}


	/**
	 * 删除部门
	 *
	 * @param id 部门 ID
	 * @return 成功、失败
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeDeptById(Integer id) {
		//级联删除部门
		List<Integer> idList = sysDeptRelationService
				.list(Wrappers.<SysDeptRelation>query().lambda()
						.eq(SysDeptRelation::getAncestor, id))
				.stream()
				.map(SysDeptRelation::getDescendant)
				.collect(Collectors.toList());

		if (CollUtil.isNotEmpty(idList)) {
			this.removeByIds(idList);
		}

		//删除部门级联关系
		sysDeptRelationService.deleteAllDeptRealtion(id);
		return Boolean.TRUE;
	}

	/**
	 * 更新部门
	 *
	 * @param sysDept 部门信息
	 * @return 成功、失败
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean updateDeptById(SysDept sysDept) {
		//更新部门状态
		this.updateById(sysDept);
		//更新部门关系
		SysDeptRelation relation = new SysDeptRelation();
		relation.setAncestor(sysDept.getParentId());
		relation.setDescendant(sysDept.getDeptId());
		sysDeptRelationService.updateDeptRealtion(relation);
		return Boolean.TRUE;
	}

	/**
	 * 查询全部部门树
	 *
	 * @return 树
	 */
//	@Override
//	public List<DeptTree> selectTree() {
//		Integer deptId = SecurityUtils.getUser().getDeptId();
//		List<Integer> roots = sysDeptLineDeptMapper.selectList(
//				Wrappers.<SysDeptLineDept>lambdaQuery()
//						.in(SysDeptLineDept::getDeptId, deptId)
//		).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
//		roots.add(deptId);
//
//		List<Integer> deptIds = sysDeptRelationMapper.selectList(
//				Wrappers.<SysDeptRelation>lambdaQuery()
//				.eq(SysDeptRelation::getAncestor, deptId)
//		).stream().map(SysDeptRelation::getDescendant).collect(Collectors.toList());
//		if (deptIds != null && !deptIds.isEmpty()) {
//			List<Integer> lineDeptIds = sysDeptLineDeptMapper.selectList(
//					Wrappers.<SysDeptLineDept>lambdaQuery()
//							.in(SysDeptLineDept::getDeptId, deptIds)
//			).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
//			deptIds.addAll(lineDeptIds);
//		}
//		List<SysDept> sysDepts = new ArrayList<>();
//		if (deptIds != null && !deptIds.isEmpty()) {
//			sysDepts = this.list(
//					Wrappers.<SysDept>lambdaQuery()
//							.in(SysDept::getDeptId, deptIds)
//							.eq(SysDept::getDelFlag, 0)
//							.orderByAsc(SysDept::getDeptType, SysDept::getSort, SysDept::getCreateTime)
//			);
//		}
//		List<DeptTree> resultDeptTrees = getDeptTree(sysDepts, roots);
//		return resultDeptTrees;
//	}

	@Override
	public List<DeptTree> selectTree(boolean selectLine) {
		Integer deptId = SecurityUtils.getUser().getDeptId();
		SysDept sysDept = getById(deptId);
		List<SysDept> sysDepts = new ArrayList<>();
		List<Integer> roots = new ArrayList<>();
		if (sysDept != null && sysDept.getParentId() != null && sysDept.getParentId().equals(0)) {
			LambdaQueryWrapper<SysDept> rootWrapper = Wrappers.<SysDept>lambdaQuery().select(SysDept::getDeptId).eq(SysDept::getParentId, 0);
			LambdaQueryWrapper<SysDept> wrapper = Wrappers.<SysDept>lambdaQuery()
					.eq(SysDept::getDelFlag, 0)
					.orderByAsc(SysDept::getDeptType, SysDept::getSort, SysDept::getCreateTime);
			if (!selectLine) {
				rootWrapper.eq(SysDept::getDeptType, 0);
				wrapper.eq(SysDept::getDeptType, 0);
			}
			roots = list(rootWrapper).stream().map(SysDept::getDeptId).collect(Collectors.toList());
			sysDepts = this.list(wrapper);
		} else {
			if (selectLine) {
				roots = sysDeptLineDeptMapper.selectList(
						Wrappers.<SysDeptLineDept>lambdaQuery()
								.in(SysDeptLineDept::getDeptId, deptId)
				).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
			}
			roots.add(deptId);
			List<Integer> deptIds = sysDeptRelationMapper.selectList(
					Wrappers.<SysDeptRelation>lambdaQuery()
							.eq(SysDeptRelation::getAncestor, deptId)
			).stream().map(SysDeptRelation::getDescendant).collect(Collectors.toList());
			if (deptIds != null && !deptIds.isEmpty() && selectLine) {
				List<Integer> lineDeptIds = sysDeptLineDeptMapper.selectList(
						Wrappers.<SysDeptLineDept>lambdaQuery()
								.in(SysDeptLineDept::getDeptId, deptIds)
				).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
				deptIds.addAll(lineDeptIds);
			}

			if (deptIds != null && !deptIds.isEmpty()) {
				sysDepts = this.list(
						Wrappers.<SysDept>lambdaQuery()
								.in(SysDept::getDeptId, deptIds)
								.eq(SysDept::getDelFlag, 0)
								.orderByAsc(SysDept::getDeptType, SysDept::getSort, SysDept::getCreateTime)
				);
			}
		}
		List<DeptTree> resultDeptTrees = getDeptTree(sysDepts, roots);
		return resultDeptTrees;
	}

	@Override
	public List<DeptTree> selectTreeLike(String name) {
		Integer deptId = SecurityUtils.getUser().getDeptId();
		List<Integer> roots = sysDeptLineDeptMapper.selectList(
				Wrappers.<SysDeptLineDept>lambdaQuery()
						.in(SysDeptLineDept::getDeptId, deptId)
		).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
		roots.add(deptId);
		List<Integer> deptIds = sysDeptRelationMapper.selectList(
				Wrappers.<SysDeptRelation>lambdaQuery()
						.eq(SysDeptRelation::getAncestor, deptId)
		).stream().map(SysDeptRelation::getAncestor).collect(Collectors.toList());
		List<Integer> lineDeptIds = sysDeptLineDeptMapper.selectList(
				Wrappers.<SysDeptLineDept>lambdaQuery()
						.in(SysDeptLineDept::getDeptId, deptIds)
		).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
		deptIds.addAll(lineDeptIds);


		/*List<SysDept> sysDepts = this.lambdaQuery()
				.in(SysDept::getDeptId, deptIds)
				.like(SysDept::getName, name)
				.list();*/

		List<SysDept> sysDepts = new ArrayList<>();
		// 模糊查询name匹配的部门节点
		List<Integer> deptIds1 = this.lambdaQuery()
				.select(SysDept::getDeptId)
				.like(SysDept::getName, name)
				.eq(SysDept::getDelFlag, 0)
				.list()
				.stream()
				.map(SysDept::getDeptId)
				.collect(Collectors.toList());
		// 查询这些节点的所有上层与下层节点
		Set<Integer> idSet = new HashSet<>();
		if (deptIds1 != null && deptIds1.size() > 0)
			idSet = sysDeptRelationMapper.selectDeptTree(deptIds1);
		if (idSet.size() > 0) {
			sysDepts = this.lambdaQuery().in(SysDept::getDeptId, idSet)
					.orderByAsc(SysDept::getDeptType, SysDept::getSort, SysDept::getCreateTime).list();
		}

		List<DeptTree> resultDeptTrees = getDeptTree(sysDepts, roots);
		return resultDeptTrees;
	}

	@Override
	public List<DeptTree> selectTreeLikeNew(String name) {
		Integer deptId = SecurityUtils.getUser().getDeptId();
		List<Integer> roots = sysDeptLineDeptMapper.selectList(
				Wrappers.<SysDeptLineDept>lambdaQuery()
						.in(SysDeptLineDept::getDeptId, deptId)
		).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
		roots.add(deptId);
		List<Integer> deptIds = sysDeptRelationMapper.selectList(
				Wrappers.<SysDeptRelation>lambdaQuery()
						.eq(SysDeptRelation::getAncestor, deptId)
		).stream().map(SysDeptRelation::getAncestor).collect(Collectors.toList());
		List<Integer> lineDeptIds = sysDeptLineDeptMapper.selectList(
				Wrappers.<SysDeptLineDept>lambdaQuery()
						.in(SysDeptLineDept::getDeptId, deptIds)
		).stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
		deptIds.addAll(lineDeptIds);


		/*List<SysDept> sysDepts = this.lambdaQuery()
				.in(SysDept::getDeptId, deptIds)
				.like(SysDept::getName, name)
				.list();*/

		List<SysDept> sysDepts = new ArrayList<>();
		// 模糊查询name匹配的（总分支）部门节点
		List<Integer> deptIds1 = this.baseMapper.selectTreeLikeNew(name);
		// 查询这些节点的所有上层与下层（总分支）节点
		Set<Integer> idSet = new HashSet<>();
		if (deptIds1 != null && deptIds1.size() > 0)
			idSet = sysDeptRelationMapper.selectDeptTree(deptIds1);
		if (idSet.size() > 0) {
			sysDepts = this.lambdaQuery().in(SysDept::getDeptId, idSet)
					.orderByAsc(SysDept::getDeptType, SysDept::getSort, SysDept::getCreateTime).list();
		}

		List<DeptTree> resultDeptTrees = getDeptTree(sysDepts, roots);
		return resultDeptTrees;
	}

	/**
	 * 同步企业微信部门
	 * @param trees
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	@Async
	public void onSyncWxDept(List<SyncSysDept> trees) {
		if(CollUtil.isEmpty(trees)) {
			return;
		}
		Map<Integer, Integer> relationMap = new HashMap<>();
		// 同步系统部门
		doSyncWxToSysDetp(trees, relationMap);
		log.info("批量同步企业微信部门到系统成功");
		// 远程同步调用
		remoteSyncCpService.syncPsnBusiness(SecurityConstants.FROM_IN);
	}


	/**
	 * 构建部门树
	 *
	 * @param depts 部门
	 * @return
	 */
	private List<DeptTree> getDeptTree(List<SysDept> depts) {
		List<DeptTree> treeList = depts.stream()
				.filter(dept -> !dept.getDeptId().equals(dept.getParentId()))
				.sorted(Comparator.comparingInt(SysDept::getSort))
				.map(dept -> {
					DeptTree node = new DeptTree();
					node.setId(dept.getDeptId());
					node.setParentId(dept.getParentId());
					node.setName(dept.getName());
					node.setOrgCode(dept.getOrgCode());
					node.setDeptType(dept.getDeptType());
					node.setSort(dept.getSort());
					node.setCreateTime(dept.getCreateTime());
					return node;
				}).collect(Collectors.toList());
		return TreeUtil.build(treeList, 0);
	}

	private List<DeptTree> getDeptTree(List<SysDept> depts, List<Integer> roots) {
		List<DeptTree> treeList = depts.stream()
				.filter(dept -> !dept.getDeptId().equals(dept.getParentId()))
				.sorted(Comparator.comparingInt(SysDept::getSort))
				.map(dept -> {
					DeptTree node = new DeptTree();
					node.setId(dept.getDeptId());
					node.setParentId(dept.getParentId());
					node.setName(dept.getName());
					node.setOrgCode(dept.getOrgCode());
					node.setDeptType(dept.getDeptType());
					node.setSort(dept.getSort());
					node.setCreateTime(dept.getCreateTime());
					return node;
				}).collect(Collectors.toList());
		List<DeptTree> results = new ArrayList<>();
		for (DeptTree deptTree : treeList) {
			if (roots.contains(deptTree.getId())) {
				results.add(deptTree);
			}
			for (DeptTree it : treeList) {
				if (it.getParentId() == deptTree.getId()) {
					if (deptTree.getChildren() == null) {
						deptTree.setChildren(new ArrayList<>());
					}
					deptTree.getChildren().add(it);
				}
			}
		}
		return results;
	}

	/**
	 * 添加条线部门
	 *
	 * @param dept 部门
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveLineDept(SysDept dept) {
		LocalDateTime now = LocalDateTime.now();

		// 获取机构树（因为条线是基于机构树构建的）
		List<DeptTree> deptTrees = getDeptTree(this.list(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptType, UpmsConstant.DEPT_TYPE_ORGAN)));
		List<SysUser> users = sysUserMapper.selectList(
				Wrappers.<SysUser>lambdaQuery()
				.select(SysUser::getUserId, SysUser::getDeptId)
				.eq(SysUser::getDelFlag, 0)
		);

		//创建**条线
		SysDept sysDept1 = new SysDept();
		BeanUtils.copyProperties(dept, sysDept1);
		sysDept1.setParentId(0);
		this.save(sysDept1);
//
		sysDeptRelationService.insertDeptRelation(sysDept1);

		for (DeptTree deptTree : deptTrees) {
			SysDept sysDept0 = new SysDept();
			BeanUtils.copyProperties(deptTree, sysDept0);
			sysDept0.setParentId(sysDept1.getDeptId());
			sysDept0.setSort(dept.getSort());
			sysDept0.setName(deptTree.getName() + dept.getName());
			sysDept0.setDeptType(UpmsConstant.DEPT_TYPE_LINE);
			sysDept0.setOrgCode(deptTree.getOrgCode());
			sysDept0.setCreateTime(now);
			this.save(sysDept0);

			SysDeptLineDept sysDeptLineDept = new SysDeptLineDept();
			sysDeptLineDept.setDeptId(deptTree.getId());
			sysDeptLineDept.setLineDeptId(sysDept0.getDeptId());
			sysDeptLineDeptMapper.insert(sysDeptLineDept);

			sysDeptRelationService.insertDeptRelation(sysDept0);

			List<SysDeptUser> sysDeptUsers = new ArrayList<>();
//			List<Integer> userIds = sysUserMapper.selectList(
//					Wrappers.<SysUser>lambdaQuery()
//							.select(SysUser::getUserId)
//							.eq(SysUser::getDeptId, deptTree.getId())
//			).stream().map(SysUser::getUserId).collect(Collectors.toList());
			List<Integer> userIds = users.stream().filter(s -> s.getDeptId() == deptTree.getId())
					.map(SysUser::getUserId)
					.collect(Collectors.toList());
			for (Integer userId : userIds) {
				SysDeptUser sysDeptUser = new SysDeptUser();
				sysDeptUser.setDeptId(sysDept0.getDeptId());
				sysDeptUser.setUserId(userId);
				sysDeptUser.setIsSelect("0");
				sysDeptUsers.add(sysDeptUser);
			}
			sysDeptUserService.saveBatch(sysDeptUsers);

			List<TreeNode> childrens = deptTree.getChildren();
			childrens.stream().forEach(s -> s.setParentId(sysDept0.getDeptId()));
			saveTree(childrens, dept.getName(), now, users);
		}
		return Boolean.TRUE;
	}
//	@Override
//	@Transactional(rollbackFor = Exception.class)
//	public Boolean saveLineDept(SysDept dept) {
//		LocalDateTime now = LocalDateTime.now();
//
//		// 获取机构树（因为条线是基于机构树构建的）
//		List<DeptTree> deptTrees = getDeptTree(this.list(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptType, UpmsConstant.DEPT_TYPE_ORGAN)));
//
//		//创建**条线
//		SysDept sysDept1 = new SysDept();
//		BeanUtils.copyProperties(dept, sysDept1);
//		sysDept1.setParentId(0);
//		this.save(sysDept1);
////
//		sysDeptRelationService.insertDeptRelation(sysDept1);
//
//		for (DeptTree deptTree : deptTrees) {
//			SysDept sysDept0 = new SysDept();
//			BeanUtils.copyProperties(deptTree, sysDept0);
//			sysDept0.setParentId(sysDept1.getDeptId());
//			sysDept0.setSort(dept.getSort());
//			sysDept0.setName(deptTree.getName() + dept.getName());
//			sysDept0.setDeptType(UpmsConstant.DEPT_TYPE_LINE);
//			sysDept0.setOrgCode(deptTree.getOrgCode());
//			sysDept0.setCreateTime(now);
//			this.save(sysDept0);
//
//			SysDeptLineDept sysDeptLineDept = new SysDeptLineDept();
//			sysDeptLineDept.setDeptId(deptTree.getId());
//			sysDeptLineDept.setLineDeptId(sysDept0.getDeptId());
//			sysDeptLineDeptMapper.insert(sysDeptLineDept);
//
//			sysDeptRelationService.insertDeptRelation(sysDept0);
//
//			List<SysDeptUser> sysDeptUsers = new ArrayList<>();
//			List<Integer> userIds = sysUserMapper.selectList(
//					Wrappers.<SysUser>lambdaQuery()
//							.select(SysUser::getUserId)
//							.eq(SysUser::getDeptId, deptTree.getId())
//			).stream().map(SysUser::getUserId).collect(Collectors.toList());
//			for (Integer userId : userIds) {
//				SysDeptUser sysDeptUser = new SysDeptUser();
//				sysDeptUser.setDeptId(sysDept0.getDeptId());
//				sysDeptUser.setUserId(userId);
//				sysDeptUser.setIsSelect("0");
//				sysDeptUsers.add(sysDeptUser);
//			}
//			sysDeptUserService.saveBatch(sysDeptUsers);
//
//			List<TreeNode> childrens = deptTree.getChildren();
//			childrens.stream().forEach(s -> s.setParentId(sysDept0.getDeptId()));
//			saveTree(childrens, dept.getName(), now);
//		}
//		return Boolean.TRUE;
//	}

//	@Override
//	@Transactional(rollbackFor = Exception.class)
//	public Boolean saveLineDept(SysDept dept) {
//		List<SysDept> sysDeptInserts = new ArrayList<>();
//		List<SysDeptLineDept> sysDeptLineDeptInserts = new ArrayList<>();
//		List<SysDeptUser> sysDeptUserInserts = new ArrayList<>();
//		LocalDateTime now = LocalDateTime.now();
//
//		// 获取机构树（因为条线是基于机构树构建的）
//		List<DeptTree> deptTrees = getDeptTree(this.list(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptType, UpmsConstant.DEPT_TYPE_ORGAN)));
//
//		//创建**条线
//		SysDept sysDept1 = new SysDept();
//		BeanUtils.copyProperties(dept, sysDept1);
//		sysDept1.setParentId(0);
//		sysDeptInserts.add(sysDept1);
//
//		for (DeptTree deptTree : deptTrees) {
//			SysDept sysDept0 = new SysDept();
//			BeanUtils.copyProperties(deptTree, sysDept0);
//			sysDept0.setParentId(sysDept1.getDeptId());
//			sysDept0.setSort(dept.getSort());
//			sysDept0.setName(deptTree.getName() + dept.getName());
//			sysDept0.setDeptType(UpmsConstant.DEPT_TYPE_LINE);
//			sysDept0.setOrgCode(deptTree.getOrgCode());
//			sysDept0.setCreateTime(now);
//			sysDeptInserts.add(sysDept0);
//
//			SysDeptLineDept sysDeptLineDept = new SysDeptLineDept();
//			sysDeptLineDept.setDeptId(deptTree.getId());
//			sysDeptLineDept.setLineDeptId(sysDept0.getDeptId());
//			sysDeptLineDeptInserts.add(sysDeptLineDept);
//
//			List<SysDeptUser> sysDeptUsers = new ArrayList<>();
//			List<Integer> userIds = sysUserMapper.selectList(
//					Wrappers.<SysUser>lambdaQuery()
//							.select(SysUser::getUserId)
//							.eq(SysUser::getDeptId, deptTree.getId())
//			).stream().map(SysUser::getUserId).collect(Collectors.toList());
//			for (Integer userId : userIds) {
//				SysDeptUser sysDeptUser = new SysDeptUser();
//				sysDeptUser.setDeptId(sysDept0.getDeptId());
//				sysDeptUser.setUserId(userId);
//				sysDeptUser.setIsSelect("0");
//				sysDeptUsers.add(sysDeptUser);
//				sysDeptUserInserts.add(sysDeptUser);
//			}
//
//			List<TreeNode> childrens = deptTree.getChildren();
//			childrens.stream().forEach(s -> s.setParentId(sysDept0.getDeptId()));
//			saveTree(childrens, dept.getName(), now, sysDeptInserts, sysDeptLineDeptInserts, sysDeptUserInserts);
//		}
//		this.saveBatch(sysDeptInserts);
//		sysDeptRelationService.insertDeptRelationBatch(sysDeptInserts);
//		sysDeptLineDeptService.saveBatch(sysDeptLineDeptInserts);
//		sysDeptUserService.saveBatch(sysDeptUserInserts);
//		return Boolean.TRUE;
//	}

//	@Override
//	@Transactional(rollbackFor = Exception.class)
//	public Boolean saveLineDept(SysDept dept) {
//		LocalDateTime now = LocalDateTime.now();
//
//		// 获取机构树（因为条线是基于机构树构建的）
//		List<DeptTree> deptTrees = getDeptTree(this.list(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptType, UpmsConstant.DEPT_TYPE_ORGAN)));
//
//		//创建**条线
////		SysDept sysDept1 = new SysDept();
////		BeanUtils.copyProperties(dept, sysDept1);
////		sysDept1.setParentId(0);
////		this.save(sysDept1);
////
////		SysDeptLineDept sysDeptLineDept = new SysDeptLineDept();
////		sysDeptLineDept.setDeptId(1);
////		sysDeptLineDept.setLineDeptId(sysDept0.getDeptId());
////		sysDeptLineDeptMapper.insert(sysDeptLineDept);
////
////		sysDeptRelationService.insertDeptRelation(sysDept0);
//
//		for (DeptTree deptTree : deptTrees) {
//			SysDept sysDept0 = new SysDept();
//			BeanUtils.copyProperties(deptTree, sysDept0);
//			sysDept0.setSort(dept.getSort());
//			sysDept0.setName(deptTree.getName() + dept.getName());
//			sysDept0.setDeptType(UpmsConstant.DEPT_TYPE_LINE);
//			sysDept0.setCreateTime(now);
//			this.save(sysDept0);
//
//			SysDeptLineDept sysDeptLineDept = new SysDeptLineDept();
//			sysDeptLineDept.setDeptId(deptTree.getId());
//			sysDeptLineDept.setLineDeptId(sysDept0.getDeptId());
//			sysDeptLineDeptMapper.insert(sysDeptLineDept);
//
//			sysDeptRelationService.insertDeptRelation(sysDept0);
//
//			List<SysDeptUser> sysDeptUsers = new ArrayList<>();
//			List<Integer> userIds = sysUserMapper.selectList(
//					Wrappers.<SysUser>lambdaQuery()
//							.select(SysUser::getUserId)
//							.eq(SysUser::getDeptId, deptTree.getId())
//			).stream().map(SysUser::getUserId).collect(Collectors.toList());
//			for (Integer userId : userIds) {
//				SysDeptUser sysDeptUser = new SysDeptUser();
//				sysDeptUser.setDeptId(sysDept0.getDeptId());
//				sysDeptUser.setUserId(userId);
//				sysDeptUser.setIsSelect("0");
//				sysDeptUsers.add(sysDeptUser);
//			}
//			sysDeptUserService.saveBatch(sysDeptUsers);
//
//			List<TreeNode> childrens = deptTree.getChildren();
//			childrens.stream().forEach(s -> s.setParentId(sysDept0.getDeptId()));
//			saveTree(childrens, dept.getName(), now);
//		}
//		return Boolean.TRUE;
//	}

	private void saveTree(List<TreeNode> childrens, String lineDeptName, LocalDateTime now, List<SysUser> users) {
		if (childrens == null || childrens.size() == 0)
			return;
		int sort = 1;
		for (TreeNode treeNode : childrens) {
			DeptTree deptTree = (DeptTree)treeNode;
			SysDept sysDept = new SysDept();
			sysDept.setDeptType(UpmsConstant.DEPT_TYPE_LINE);
			sysDept.setParentId(deptTree.getParentId());
			sysDept.setOrgCode(deptTree.getOrgCode());
			sysDept.setName(deptTree.getName() + lineDeptName);
			sysDept.setCreateTime(now);
			sysDept.setSort(sort++);
			this.baseMapper.insert(sysDept);
			sysDeptRelationService.insertDeptRelation(sysDept);
			SysDeptLineDept sysDeptLineDept = new SysDeptLineDept();
			sysDeptLineDept.setDeptId(deptTree.getId());
			sysDeptLineDept.setLineDeptId(sysDept.getDeptId());
			sysDeptLineDeptMapper.insert(sysDeptLineDept);
			List<SysDeptUser> sysDeptUsers = new ArrayList<>();
//			List<Integer> userIds = sysUserMapper.selectList(
//					Wrappers.<SysUser>lambdaQuery()
//					.select(SysUser::getUserId)
//					.eq(SysUser::getDeptId, deptTree.getId())
//			).stream().map(SysUser::getUserId).collect(Collectors.toList());
			List<Integer> userIds = users.stream().filter(s -> s.getDeptId() == deptTree.getId())
					.map(SysUser::getUserId)
					.collect(Collectors.toList());
			for (Integer userId : userIds) {
				SysDeptUser sysDeptUser = new SysDeptUser();
				sysDeptUser.setDeptId(sysDept.getDeptId());
				sysDeptUser.setUserId(userId);
				sysDeptUser.setIsSelect("0");
				sysDeptUsers.add(sysDeptUser);
			}
			sysDeptUserService.saveBatch(sysDeptUsers);

			List<TreeNode> grandsons = treeNode.getChildren();
			if (grandsons != null) {
				grandsons.stream().forEach(s -> s.setParentId(sysDept.getDeptId()));
			}
			saveTree(grandsons, lineDeptName, now, users);
		}
	}

	private void saveTree(
			List<TreeNode> childrens,
			String lineDeptName,
			LocalDateTime now,
			List<SysDept> sysDeptInserts,
			List<SysDeptLineDept> sysDeptLineDeptInserts,
			List<SysDeptUser> sysDeptUserInserts
	) {
		if (childrens == null || childrens.size() == 0)
			return;
		int sort = 1;
		for (TreeNode treeNode : childrens) {
			DeptTree deptTree = (DeptTree)treeNode;
			SysDept sysDept = new SysDept();
			sysDept.setDeptType(UpmsConstant.DEPT_TYPE_LINE);
			sysDept.setParentId(deptTree.getParentId());
			sysDept.setOrgCode(deptTree.getOrgCode());
			sysDept.setName(deptTree.getName() + lineDeptName);
			sysDept.setCreateTime(now);
			sysDept.setSort(sort++);
			sysDeptInserts.add(sysDept);
			SysDeptLineDept sysDeptLineDept = new SysDeptLineDept();
			sysDeptLineDept.setDeptId(deptTree.getId());
			sysDeptLineDept.setLineDeptId(sysDept.getDeptId());
			sysDeptLineDeptInserts.add(sysDeptLineDept);
			List<Integer> userIds = sysUserMapper.selectList(
					Wrappers.<SysUser>lambdaQuery()
							.select(SysUser::getUserId)
							.eq(SysUser::getDeptId, deptTree.getId())
			).stream().map(SysUser::getUserId).collect(Collectors.toList());
			for (Integer userId : userIds) {
				SysDeptUser sysDeptUser = new SysDeptUser();
				sysDeptUser.setDeptId(sysDept.getDeptId());
				sysDeptUser.setUserId(userId);
				sysDeptUser.setIsSelect("0");
				sysDeptUserInserts.add(sysDeptUser);
			}

			List<TreeNode> grandsons = treeNode.getChildren();
			if (grandsons != null) {
				grandsons.stream().forEach(s -> s.setParentId(sysDept.getDeptId()));
			}
			saveTree(grandsons, lineDeptName, now, sysDeptInserts, sysDeptLineDeptInserts, sysDeptUserInserts);
		}
	}

	/**
	 * 修改条线部门
	 *
	 * @param dept 部门
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public R updateLineDept(SysDept dept) {
		SysDept localDept = this.baseMapper.selectById(dept.getDeptId());
		Integer type = localDept.getDeptType();
		Integer parentId = localDept.getParentId();
		if (type == null || type.equals(0) || parentId == null || !parentId.equals(0)) {
			return R.failed("只允许对**条线从根节点统一修改该条线");
		}
		String localDeptName = localDept.getName();
		SysDept sysDept0 = new SysDept();
		BeanUtils.copyProperties(dept, sysDept0);
		this.saveOrUpdate(sysDept0);

		this.baseMapper.updateLines(dept.getDeptId(), dept.getName(), localDeptName);

		return R.ok();
	}

	/**
	 * 删除条线部门
	 *
	 * @param deptId 部门
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean deleteLineDept(Integer deptId) {
		List<Integer> deptIds = sysDeptRelationMapper.selectList(
				Wrappers.<SysDeptRelation>lambdaQuery()
				.select(SysDeptRelation::getDescendant)
				.eq(SysDeptRelation::getAncestor, deptId)
		).stream().map(s -> s.getDescendant()).collect(Collectors.toList());
		if (deptIds == null || deptIds.size() == 0)
			return Boolean.FALSE;
		this.baseMapper.delete(
				Wrappers.<SysDept>lambdaQuery()
				.in(SysDept::getDeptId, deptIds)
		);
		sysDeptRelationMapper.delete(
				Wrappers.<SysDeptRelation>lambdaQuery()
				.in(SysDeptRelation::getAncestor, deptIds)
		);
		sysDeptLineDeptMapper.delete(
				Wrappers.<SysDeptLineDept>lambdaQuery()
						.in(SysDeptLineDept::getLineDeptId, deptIds)
		);
		sysDeptUserService.remove(
				Wrappers.<SysDeptUser>lambdaQuery()
				.in(SysDeptUser::getDeptId, deptIds)
		);
		return Boolean.TRUE;
	}

	public Integer getDeptId(Integer lineDeptId) {
		SysDeptLineDept sysDeptLineDept = sysDeptLineDeptMapper.selectOne(
				Wrappers.<SysDeptLineDept>lambdaQuery()
						.eq(SysDeptLineDept::getLineDeptId, lineDeptId)
		);
		return sysDeptLineDept.getDeptId();
	}

	public List<DeptLineDeptVO> getChildrens(Integer lineDeptId) {
		return this.baseMapper.getChildrens(lineDeptId);
	}

	public List<DeptLineDeptVO> getSelectDepts(List<Integer> lineDeptIds) {
		return this.baseMapper.getSelectDepts(lineDeptIds);
	}
	public List<Integer> getAllDeptsOrg(Integer deptId) {
		return this.baseMapper.getWxDeptIdsOrg(deptId);
	}

	@Override
	public List<Integer> getAllDeptsOrg(List<Integer> deptIds) {
		return deptIds.isEmpty() ? new ArrayList<Integer>() : this.baseMapper.getWxDeptIdsOrgByDeptIds(deptIds);
	}

	public List<Integer> getAllDeptsLine(List<Integer> deptIds) {
		return this.baseMapper.getWxDeptIdsLine(deptIds);
	}

	public List<Map<String, Integer>> getChildrensOrg(Integer deptId, Integer deptType) {
		if (deptType == UpmsConstant.DEPT_TYPE_LINE) {
			deptId = sysDeptLineDeptMapper.selectOne(
					Wrappers.<SysDeptLineDept>lambdaQuery()
					.eq(SysDeptLineDept::getLineDeptId, deptId)
			).getDeptId();
		}
		return this.baseMapper.getChildrensOrg(deptId);
	}

	public Integer getWxDeptId(Integer deptId, Integer deptType) {
		if (deptType == UpmsConstant.DEPT_TYPE_LINE) {
			deptId = sysDeptLineDeptMapper.selectOne(
					Wrappers.<SysDeptLineDept>lambdaQuery()
							.eq(SysDeptLineDept::getLineDeptId, deptId)
			).getDeptId();
		}
		return sysWxDeptRelationService.getOne(
				Wrappers.<SysWxDeptRelation>lambdaQuery()
				.eq(SysWxDeptRelation::getSysDeptId, deptId)
		).getWxDeptId();
	}

	public Integer getWxDeptId(SysDept sysDept) {
		Integer deptType = sysDept.getDeptType();
		Integer deptId = sysDept.getDeptId();
		// 找到条线对应的机构号
		if (deptType == UpmsConstant.DEPT_TYPE_LINE) {
			Integer parentId = sysDept.getParentId();
			// 如果是**条线 从其下的华融湘江银行**条线开始查
			if (parentId != null && parentId.equals(0)) {
				deptId = this.getOne(
						Wrappers.<SysDept>lambdaQuery()
						.select(SysDept::getDeptId)
						.eq(SysDept::getParentId, deptId)
						.eq(SysDept::getDelFlag, 0)
				).getDeptId();
			}
			deptId = sysDeptLineDeptMapper.selectOne(
					Wrappers.<SysDeptLineDept>lambdaQuery()
							.eq(SysDeptLineDept::getLineDeptId, deptId)
			).getDeptId();
		}
		// 返回机构对应的微信机构号
		return sysWxDeptRelationService.getOne(
				Wrappers.<SysWxDeptRelation>lambdaQuery()
						.eq(SysWxDeptRelation::getSysDeptId, deptId)
		).getWxDeptId();
	}

	public IPage getChildrenPage(Integer deptId, Integer deptType, Page page) {
		if (deptType == UpmsConstant.DEPT_TYPE_LINE) {
			return this.baseMapper.getLineChildrenPage(page, deptId);
		}
		return this.baseMapper.getChildrenPage(page, deptId);
	}

	public Set<Integer> getSelectedDepts(String mobile) {
		SysUser sysUser = sysUserMapper.selectList(
				Wrappers.<SysUser>lambdaQuery()
				.eq(SysUser::getPhone, mobile)
		).get(0);
		Integer userId = sysUser.getUserId();
		Integer deptId = sysUser.getDeptId();
		List<Integer> selectedDepts = sysDeptUserService.list(
				Wrappers.<SysDeptUser>lambdaQuery()
				.eq(SysDeptUser::getUserId, userId)
				.eq(SysDeptUser::getIsSelect, 1)
		).stream().map(SysDeptUser::getDeptId).collect(Collectors.toList());
		selectedDepts.add(deptId);
		Set<Integer> allDepts = sysDeptRelationService.list(
				Wrappers.<SysDeptRelation>lambdaQuery()
				.in(SysDeptRelation::getAncestor, selectedDepts)
		).stream().map(SysDeptRelation::getDescendant).collect(Collectors.toSet());
		return allDepts;
	}

	@Override
	public IPage getChildrenPageByObjectId(Integer deptId, Integer deptType, Page page, Integer objectId) {
		if (deptType == UpmsConstant.DEPT_TYPE_LINE) {
			return this.baseMapper.getLineChildrenPage(page, deptId);
		}
		return this.baseMapper.getChildrenPageByObjectId(page, deptId,objectId);
	}

	@Override
	public List<Integer> getAllZhLine() {
		List<SysDeptLineDept> relations = sysDeptLineDeptMapper.selectList(
				Wrappers.<SysDeptLineDept>lambdaQuery()
				.eq(SysDeptLineDept::getDeptId, 1)
		);
		if (relations != null && !relations.isEmpty()) {
			return relations.stream().map(SysDeptLineDept::getLineDeptId).collect(Collectors.toList());
		}
		return new ArrayList<>();
	}

	@Override
	public List<String> getAllChildrenOrgCode(Integer deptId) {
		return baseMapper.getAllChildrenOrgCode(deptId);
	}

	@Override
	public List<SysDept> getLowerDeptsByList(List<Integer> depts) {
		LinkedList<SysDept> list = new LinkedList<>();
		List<SysDept> allDepts = list(Wrappers.emptyWrapper());
		getLowerDeptsByListPrivate(depts, list, allDepts);
		return list.stream().distinct().collect(Collectors.toList());
	}

//	private void getLowerDeptsByListPrivate(List<Integer> depts,List<SysDept> list){
//		for (SysDept dept : list(Wrappers.<SysDept>lambdaQuery().in(SysDept::getDeptId, depts))) {
//			list.add(dept);
//			List<SysDept> sysDepts = list(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getParentId, dept.getDeptId()));
//			if (!sysDepts.isEmpty()){
//				getLowerDeptsByListPrivate(sysDepts.stream().map(SysDept::getDeptId).collect(Collectors.toList()), list);
//				list.addAll(sysDepts);
//			}
//		}
//	}

	private void getLowerDeptsByListPrivate(List<Integer> depts, List<SysDept> list, List<SysDept> allDepts) {
		List<SysDept> baseDepts = allDepts.stream().filter(s -> {
			return depts.contains(s.getDeptId());
		}).collect(Collectors.toList());
		for (SysDept dept : baseDepts) {
			list.add(dept);
			List<SysDept> sysDepts = allDepts.stream().filter(s -> {
				Integer parentId = s.getParentId();
				return parentId.equals(dept.getDeptId());
			}).collect(Collectors.toList());
			if (!sysDepts.isEmpty()){
				getLowerDeptsByListPrivate(sysDepts.stream().map(SysDept::getDeptId).collect(Collectors.toList()), list, allDepts);
				list.addAll(sysDepts);
			}
		}
	}


	// 同步企业微信部门到系统部门
	private void doSyncWxToSysDetp(List<SyncSysDept> trees, Map<Integer, Integer> wxSysMap) {
		for (SyncSysDept syncSysDept : trees) {
			if(syncSysDept.getOpt() == SyncConstant.NEW_OPT) {
                Integer sysParentDeptId = wxSysMap.get(syncSysDept.getWxParentDeptId());
                if (sysParentDeptId == null) {
                    sysParentDeptId = syncSysDept.getSysParentDeptId();
                }
                //新增
				SysDept sysDept = new SysDept();
				sysDept.setName(syncSysDept.getDeptName());
				sysDept.setParentId(sysParentDeptId);
				sysDept.setOrgCode(syncSysDept.getOrgCode());
				sysDept.setSort(1);
				sysDept.setDeptType(UpmsConstant.DEPT_TYPE_ORGAN);
				this.save(sysDept);
				sysDeptRelationService.insertDeptRelation(sysDept);
				//新增关联
				SysWxDeptRelation sysWxDeptRelation = new SysWxDeptRelation();
				sysWxDeptRelation.setSysDeptId(sysDept.getDeptId());
				sysWxDeptRelation.setWxDeptId(syncSysDept.getWxDeptId());
				sysWxDeptRelationService.save(sysWxDeptRelation);
				//设置下一个新增对象的父id
                wxSysMap.put(syncSysDept.getWxDeptId(), sysDept.getDeptId());
			}
			else if(syncSysDept.getOpt() == SyncConstant.UPDATE_OPT) {
				//更新
				SysDept sysDept = new SysDept();
				sysDept.setDeptId(syncSysDept.getSysDeptId());
				sysDept.setName(syncSysDept.getDeptName());
				sysDept.setOrgCode(syncSysDept.getOrgCode());
				sysDept.setParentId(syncSysDept.getSysParentDeptId());
				updateDeptById(sysDept);
			}
			else if(syncSysDept.getOpt() == SyncConstant.DELETE_OPT) {
				//级联删除
				removeDeptById(syncSysDept.getSysDeptId());
				//删除关联
				sysWxDeptRelationService.remove(Wrappers.<SysWxDeptRelation>lambdaQuery()
						.eq(SysWxDeptRelation::getSysDeptId, syncSysDept.getSysDeptId())
						.eq(SysWxDeptRelation::getWxDeptId, syncSysDept.getWxDeptId()));
			}

			//是否有子集合
			List<SyncSysDept> subTrees = syncSysDept.getChildren();
			if(subTrees != null && !subTrees.isEmpty()) {
				doSyncWxToSysDetp(subTrees, wxSysMap);
			}
		}
	}
}
